#ifndef HOST_GCC


#include <stdint.h>
#include <irt_syscalls.h>

typedef void (*irt_exit_t)(int status);
typedef size_t (*irt_query_t)(const char* interface_ident, void* table, size_t tablesize);
typedef int (*irt_write_t)(int fd, const void* buf, size_t count, size_t* nwrote);
typedef void* (*irt_tls_get_t)(void);
typedef int (*irt_tls_init_t)(void* thread_ptr);

static irt_query_t s_query;
static irt_exit_t s_exit;
static irt_write_t s_write;
static irt_tls_init_t s_tls_init;
static irt_tls_get_t s_tls_get;


#define AT_NULL 0
#define AT_SYSINFO 32
void _init_basic(uintptr_t* auxv) {
	for (; *auxv != AT_NULL; auxv += 2) {
		if (*auxv == AT_SYSINFO) {
			s_query = (irt_query_t) auxv[1];
			break;
		}
	}

	if (s_query) {
		struct nacl_irt_basic basic;
		s_query(NACL_IRT_BASIC_v0_1, &basic, sizeof(basic));
		s_exit = basic.exit;

		struct nacl_irt_dev_fdio fdio;
		do {
			if (s_query(NACL_IRT_DEV_FDIO_v0_3, &fdio, sizeof(struct nacl_irt_dev_fdio))
					== sizeof(struct nacl_irt_dev_fdio)) break;
			if (s_query(NACL_IRT_DEV_FDIO_v0_2, &fdio, sizeof(struct nacl_irt_dev_fdio_v0_2))
					== sizeof(struct nacl_irt_dev_fdio_v0_2)) break;
			if (s_query(NACL_IRT_DEV_FDIO_v0_1, &fdio, sizeof(struct nacl_irt_fdio))
					== sizeof(struct nacl_irt_fdio)) break;
		} while (0);
		s_write = fdio.write;

    struct nacl_irt_tls funcs;
    do {
      if (s_query(NACL_IRT_TLS_v0_1, &funcs, sizeof(struct nacl_irt_tls))
          == sizeof(struct nacl_irt_tls)) break;
    } while (0);
    s_tls_init = funcs.tls_init;
    s_tls_get = funcs.tls_get;
  }
}

#ifdef __x86_64__
void* __attribute__ ((const)) __nacl_read_tp () {
  return s_tls_get();
}

void* __nacl_add_tp(ptrdiff_t off) {
  return (char*) s_tls_get() + off;
}
#endif


void exit(int val) {
	s_exit(val);
	while(1);
}

int puts(const char *str) {
	size_t len = 0;
	for (;str[len];len++);

	size_t written;
	s_write(1, str, len, &written);
	return written;
}

int main(int argc, char* argv[]);

void _start(unsigned **info) {
  int envc = (int)info[1];
  int argc = (int)info[2];
  char **argv = (char**)&info[3];
  char **envp = argv + argc + 1;
  unsigned *auxv = (unsigned *)(envp + envc + 1);
  static char buf[sizeof(void*) * 7];

  _init_basic(auxv);
  exit(main(argc, argv));
}

#endif